<?php

require_once 'Request.php';
require_once 'Controller.php';

class ActionHandler extends Controller{
    
    private $actionParam = null;
    private $actions = array();

    protected function process(){parent::process();}

    public function initialize(){
        parent::initialize();
    }

    public function setActionParam($param){
        Checker::checkString($param);
        $this->actionParam = $param;
    }

    public function registerAction($name, $method = null, $handle = null){
        if($handle == null)$handle = $name;
        else Checker::checkString($name);
        Checker::checkString($handle);
        if($this->actionParam === null)$actionParam = $this->createUniqueHashId();
        $this->actions[$name] = array("method" => $method,
                                      "handle" => $handle);
        if($method === null || $method === Request::METHOD_GET)
            $this->reserveParameter($this->actionParam);
    }

    public function processRequest(){
        $this->processActions();
        parent::processRequest();
    }

    public function runAction($name){
        $handle = $this->actions['handle'];
        $this->$handle();
    }

    public function createActionAddress($name, $override = false){
        if(isset($this->actions[$name])){
            $action = $this->actions[$name];
            if($override)
                return $this->createOverrideActionAddress($action['handle']);
            return $this->createReloadAddress(array($this->actionParam => $name));
        }
    }

    protected function processActions(){
        if($this->actionParam !== null){
            $action = $this->getRequest()->getParameter($this->actionParam);
            if($action !== null){
                $method = $this->actions[$action]['method'];
                if($method === null || $method == $this->getRequest()->getMethod())
                    $this->runAction($action);
            }
        }
    }

    /**
     * Creates an address for override action of provided handle method name.
     * The purpose of override action is to replace whole response to the user
     * with output of the handle method. This behavior is necessary when AJAX
     * request needs to be handled by a component that is inside a container.
     * @return string  the created address
     */
    protected function createOverrideActionAddress($handle){
        Checker::checkString($handle);
        $cn = 0;
        $address = '';
        $comp = $this;
        $owner = $this->getOwner();
        while($owner !== null){
            $address = "&amp;c$cn=".$comp->getName().$address;
            $comp = $owner;
            $owner = $comp->getOwner();
            $cn++;
        }
        $address = $_SERVER['PHP_SELF']."?cn=$cn&amp;action=$handle$address";
        return $address;
    }

}
?>
